﻿using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace CommonLib.Util;

public static class OutPutUtil
{

    public static void FormatLines(List<string> Lines, string file)
    {
        var ext = Path.GetExtension(file);
        switch (ext)
        {
            case ".java":
                FormatJavaLines(Lines, file);
                break;
            case ".vb":
                FormatVBLines(Lines, file);
                break;
            case ".html":
                FormatHtml(Lines, file);
                break;
            case ".xaml":
                FormatXaml(Lines, file);
                break;
            default:
                FormatCsharpLines(Lines, file);
                break;
        }
    }


    /// <summary>
    /// Pas 转换后文件Format
    /// </summary>
    /// <param name="Lines">转换后文件一览</param>
    /// <param name="file">转换前文件</param>
    public static void FormatCsharpLines(List<string> Lines, string file)
    {
        int num = 0;
        var list = new List<string>();
        bool IsCase = false;
        var prp = new List<string>() { "public", "protected", "private" };
        var keywords = new List<string> { "return", "continue", "break" };
        for (int i = 0; i < Lines.Count; i++)
        {
            var line = Lines[i];
            if (string.IsNullOrEmpty(line))
            {
                continue;
            }
            if (line.StartsWith("//"))
            {
                list.Add(line.Space(num));
                continue;
            }
            if (line.Equals("{"))
            {
                list.Add(line.Space(num));
                num++;
                continue;
            }
            else if (line.Equals("}"))
            {
                num--;
                list.Add(line.Space(num));
                continue;
            }
            else if (IsCase && line.Equals("break"))
            {
                list.Add("break;".Space(num));
                num--;
                IsCase = false;
                continue;
            }
            else if (IsCase && line.StartsWith("return"))
            {
                list.Add($"{line.Space(num)};");
                num--;
                IsCase = false;
                continue;
            }
            else if (line.EndsWith(":"))
            {
                if (!IsCase)
                {
                    list.Add(line.Space(num));
                    IsCase = true;
                    num++;
                }
                else
                {
                    num--;
                    list.Add(line.Space(num));
                    num++;
                }
                continue;
            }

            var next = i == Lines.Count - 1 ? "" : Lines[i + 1];
            if (!next.Equals("{") && !line.EndsWith(",") && !line.Contains(';') && !line.Contains(':')
                && !next.Trim().StartsWith("=>")) line += ";";
            if (line.Contains(':') && (line.Contains('"') || line.Contains('?'))) line += ";";
            if (prp.Any(line.StartsWith))
            {
                int idx = list.Count - 1;
                while (true)
                {
                    var pre = list[idx].Trim();
                    if (pre.Equals("{") || pre.Equals("}") || pre.StartsWith("=>")
                        || prp.Any(pre.StartsWith)) break;
                    idx--;
                }
                if (idx == list.Count - 1) list.Add("");
                else list.Insert(idx + 1, "");
            }
            list.Add(line.Space(num));
        }

        var dir = Path.GetDirectoryName(file);
        dir = dir!.Replace(ConstUtil.InPath, ConstUtil.OutPath);
        if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
        var oup = Path.Combine(dir, $"{Path.GetFileNameWithoutExtension(file)}.cs");
        File.WriteAllLines(oup, list);
    }


    private static void FormatJavaLines(List<string> Lines, string file)
    {
        int num = 0;
        var list = new List<string>();
        bool IsCase = false;
        for (int i = 0; i < Lines.Count; i++)
        {
            var line = Lines[i];
            if (string.IsNullOrEmpty(line))
            {
                list.Add(line);
                continue;
            }
            if (line.StartsWith("//"))
            {
                list.Add(line.Space(num));
                continue;
            }
            if (line.EndsWith("{"))
            {
                if (Lines[i - 1].Equals("}") && (line.StartsWith("else") || line.StartsWith("catch")))
                {
                    list[^1] = $"{list[^1]} {line}";
                }
                else list.Add(line.Space(num));
                num++;
                continue;
            }
            if (line.StartsWith("}"))
            {
                num--;
                list.Add(line.Space(num));
                continue;
            }
            if (IsCase && line.Equals("break"))
            {
                list.Add("break;".Space(num));
                num--;
                IsCase = false;
                continue;
            }
            else if (IsCase && line.StartsWith("return"))
            {
                list.Add($"{line.Space(num)};");
                num--;
                IsCase = false;
                continue;
            }
            else if (line.EndsWith(":"))
            {
                if (!IsCase)
                {
                    list.Add(line.Space(num));
                    IsCase = true;
                    num++;
                }
                else
                {
                    num--;
                    list.Add(line.Space(num));
                    num++;
                }
                continue;
            }
            list.Add($"{line.Space(num)};");
        }
        var dir = Path.GetDirectoryName(file);
        dir = dir!.Replace(ConstUtil.InPath, ConstUtil.OutPath);
        if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
        var oup = Path.Combine(dir, $"{Path.GetFileNameWithoutExtension(file)}.java");
        File.WriteAllLines(oup, list);
    }


    private static void FormatVBLines(List<string> Lines, string file)
    {

    }

    private static void FormatXaml(List<string> Lines, string file)
    {
        var list = new List<string>();
        int num = 0;
        for (int i = 0; i < Lines.Count; i++)
        {
            var line = Lines[i];
            if (line.StartsWith("</"))
            {
                num--;
                list.Add(line.Space(num));
                continue;
            }
            if (line.StartsWith("<") && !line.Contains("</") && !line.EndsWith("/>"))
            {
                list.Add(line.Space(num));
                if (line.EndsWith(">")) num++;
                continue;
            }
            if (!line.StartsWith("<"))
            {
                list.Add(line.Space(num + 1));
                if (line.EndsWith(">")) num++;
                continue;
            }
            list.Add(line.Space(num));
        }
        var dir = Path.GetDirectoryName(file);
        dir = dir!.Replace(ConstUtil.InPath, ConstUtil.OutPath);
        if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
        var oup = Path.Combine(dir, $"{Path.GetFileNameWithoutExtension(file)}.xaml");
        File.WriteAllLines(oup, list);
    }


    private static void FormatHtml(List<string> Lines, string file)
    {
        var list = new List<string>();
        int num = 0;
        for (int i = 0; i < Lines.Count; i++)
        {
            var line = Lines[i];
            if (i <= 1)
            {
                list.Add(line);
                continue;
            }
            if (line.StartsWith("</"))
            {
                num--;
                list.Add(line.Space(num));
                continue;
            }
            if (line.StartsWith("<") && !line.StartsWith("<meta") && !line.Contains("</"))
            {
                list.Add(line.Space(num));
                num++;
                continue;
            }
            list.Add(line.Space(num));
        }
        var dir = Path.GetDirectoryName(file);
        dir = dir!.Replace(ConstUtil.InPath, ConstUtil.OutPath);
        if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
        var oup = Path.Combine(dir, $"{Path.GetFileNameWithoutExtension(file)}.html");
        File.WriteAllLines(oup, list);
    }
}
